/**
 * 
 */
package compilador.analizadorSintactico.categoriasSintacticas;

import java.util.ArrayList;

import javax.swing.tree.DefaultMutableTreeNode;

import compilador.analizadorLexico.simbolos.SimboloLexico;
import compilador.analizadorSemantico.tablaSimbolos.TablaSimboloSemantico;
import compilador.analizadores.AnalizadorSemantico;
import compilador.interfaces.Asignable;

/**
 * @author Nolberto Castellanos Rodriguez
 * @author Yurani Alejandra Salamanca Lotero
 *
 * Clase que representa la declaracion de un atributo
 */
public class Atributo {
	
//	-------------------------------------------------------------------------------------------------
//	ATRIBUTOS
//	-------------------------------------------------------------------------------------------------

	/**
	 * Atributo que representa la visibilidad de un atributo
	 */
	private Visibilidad visibilidad;
	 
	/**
	 *  Atributo que contiene el tipo de dato del atributo
	 */
	private TipoDato tipoDato;
	
	/**
	 *  Identificador del atributo
	 */
	private SimboloLexico identificadorAtributo;
	
	/**
	 * Valor que puede tener el atributo
	 */
	private Asignable valor;
	
//	-------------------------------------------------------------------------------------------------
//	CONSTRUCTOR
//	-------------------------------------------------------------------------------------------------

	/**
	 * Constructor que permite construir un atributo
	 * @param visibilidad. Visibilidad del atributo
	 * @param tipoDato. Tipo de dato que tiene al atributo
	 * @param identificadorAtributo. Nombre del atributo
	 * @param valor. Valor que tiene asignado  el atributo
	 */
	public Atributo(Visibilidad visibilidad, TipoDato tipoDato, SimboloLexico identificadorAtributo, Asignable valor) {
		super();
		this.visibilidad = visibilidad;
		this.tipoDato = tipoDato;
		this.identificadorAtributo = identificadorAtributo;
		this.valor = valor;
	}
	
//	-------------------------------------------------------------------------------------------------
//	METODOS
//	-------------------------------------------------------------------------------------------------	
	
	public String getJavaCode(){
		String retornable = "";
		
		if(visibilidad != null)
			retornable += visibilidad.getJavaCode()+" ";
		
		if(tipoDato != null)
			retornable += tipoDato.getJavaCode();
		
		retornable += identificadorAtributo.getLexema()+" ";
		
		if(valor != null)
			retornable = valor.getJavaCode()+";\n";
		
		return retornable;
	}
	
	/**
	 * Metodo que permite agregar hojas al nodo de la clase
	 * @return el nodo de la clase con sus hojas
	 */
	public DefaultMutableTreeNode getArbolVisual(){
		DefaultMutableTreeNode miRaiz =  new  DefaultMutableTreeNode("Atributo");
		
		if(visibilidad != null)
			miRaiz.add(visibilidad.getArbolVisual());
		
		if(tipoDato != null)
			miRaiz.add(tipoDato.getArbolVisual());
		
		if(identificadorAtributo != null)
			miRaiz.add(new DefaultMutableTreeNode(identificadorAtributo.getLexema()));
		
		if(valor != null)
			miRaiz.add(valor.getArbolVisual());
		
		return miRaiz;
	}
	
	/**
	 * @param ts
	 * @param errores
	 * @param claseActual
	 * @param metodoActual
	 */
	public void analizarSemantica(TablaSimboloSemantico ts,	ArrayList<SimboloError> errores, String claseActual, String metodoActual) {
		if(valor != null){
			if(valor instanceof IdentificadorValor){
				if(!ts.esRepetido(((IdentificadorValor) valor).getIdentificador().getLexema())){
					errores.add(new SimboloError("El identificador del valor no se encuentra instanciado",
							((IdentificadorValor) valor).getIdentificador().getFila(),
							((IdentificadorValor) valor).getIdentificador().getColumna()));
				}
				else {
					String tipo2 = ts.getSimbolo(((IdentificadorValor) valor).getIdentificador().getLexema(), claseActual).getTipoDato();
					if(!AnalizadorSemantico.verificarCompatibilidad(tipoDato.getTipoDato().getLexema(), tipo2)){
						errores.add(new SimboloError("Los tipos no son compatibles", ((IdentificadorValor) valor).getIdentificador().getFila() 
								, ((IdentificadorValor) valor).getIdentificador().getColumna()));
					}
				}
			}
		}
	}
	
	
	
//	-------------------------------------------------------------------------------------------------
//	Getter's and Setter's
//	-------------------------------------------------------------------------------------------------

	/**
	 * Metodo que nos retorna el valor de visibilidad
	 * @return  visibilidad. Valor retornado
	 */
	public Visibilidad getVisibilidad() {
		return visibilidad;
	}

	/**
	 * Metodo que permite asignar el valor de visibilidad
	 * @param visibilidad. Valor a asignar visibilidad
	 */
	public void setVisibilidad(Visibilidad visibilidad) {
		this.visibilidad = visibilidad;
	}

	/**
	 * Metodo que nos retorna el valor de tipoDato
	 * @return  tipoDato. Valor retornado
	 */
	public TipoDato getTipoDato() {
		return tipoDato;
	}

	/**
	 * Metodo que permite asignar el valor de tipoDato
	 * @param tipoDato. Valor a asignar tipoDato
	 */
	public void setTipoDato(TipoDato tipoDato) {
		this.tipoDato = tipoDato;
	}

	/**
	 * Metodo que nos retorna el valor de identificadorAtributo
	 * @return  identificadorAtributo. Valor retornado
	 */
	public SimboloLexico getIdentificadorAtributo() {
		return identificadorAtributo;
	}

	/**
	 * Metodo que permite asignar el valor de identificadorAtributo
	 * @param identificadorAtributo. Valor a asignar identificadorAtributo
	 */
	public void setIdentificadorAtributo(SimboloLexico identificadorAtributo) {
		this.identificadorAtributo = identificadorAtributo;
	}

	/**
	 * Metodo que nos retorna el valor de valor
	 * @return  valor. Valor retornado
	 */
	public Asignable getValor() {
		return valor;
	}

	/**
	 * Metodo que permite asignar el valor de valor
	 * @param valor. Valor a asignar valor
	 */
	public void setValor(Asignable valor) {
		this.valor = valor;
	}

}
